package com.ease.framework {

import com.ease.util.gc.SharedReference;

import mx.core.IMXMLObject;

/**
 * A MediatorMap defines a mapping of view classes to mediator classes, so that the
 * framework can construct a mediator and initialize it with the corresponding view
 * whenever a new view comes on the stage.
 *
 * <p>In other words, a mediator map declares the <i>default</i> mediator type for a view
 * type. The app can however create a mediator (for some view) on its own and register it
 * with the framework dynamically.
 *
 * <p>A single mediator map can have any number of view-type to mediator-type mappings.
 *
 * <p>A MediatorMap is usually defined in mxml, although it can also be defined in
 * ActionScript. It is registered with <i>a</i> ViewRegistry (or <i>the</i> global
 * ViewRegistry) either explicitly by calling addMediatorMap, or implicitly by declaring
 * an instance of the map somewhere in the application mxml.
 *
 * <p>Defining a mediator map is optional, and doesn't have to be done if the
 * [DefaultMediator] metatag is used on the view classes. That is an alternate way of
 * specifying the same information that a mediator map provides.
 *
 * <p>An app may prefer the map approach (compared to the [DefaultMediator] style) due to
 * the following reasons:
 *
 * <ul>
 * <li> It has slightly better performance characteristics when creating a highly
 * nested view all at once (as opposed to creating it incrementally as needed)
 * <li> It eliminates the need to include the mediator types in the build config of the
 * project to make sure that they're included in the binaries. The compiler may not
 * include them if they're not referenced anywhere (referencing them in the annotations
 * doesn't count since metatags are essentially just text).
 * </ul>
 *
 * @see ViewRegistry
 */
public class MediatorMap implements IMXMLObject
{
   private var _registryRef:SharedReference = SharedReference.newReference(ViewRegistry);

   public function MediatorMap() {
      this.registry = ViewRegistry.instance;
   }

   //------------------------------------------------------------------------------------
   // Instance properties
   // The property provider used avoids directly referencing the global instance.
   // This is done to simplify the object graph for Memory Profiler.

   /**
    * The ViewRegistry that the mediators in this map are to be registered with.
    */
   public function get registry():ViewRegistry {
      return _registryRef.object;
   }

   /**
    * @private
    */
   public function set registry(value:ViewRegistry):void {
      _registryRef.object = value;
   }

   /**
    * The collection of MediatorMapping instances that are part of this mediator map.
    */
   [ArrayElementType("com.ease.framework.MediatorMapping")]
   public var mappings:Array;

   /**
    * Called after the implementing object has been created and all component properties
    * specified on the MXML tag have been initialized.
    *
    * @param document
    *  The MXML document that created this object.
    * @param id
    *  The identifier used by document to refer to this object.
    *
    * @internal The @inheritDoc tag doesn't work here or else that'd be used rather than
    * copy-pasting the doc from the interface.
    */
   public function initialized( document:Object, id:String ):void {
      registry.addMediatorMap( this );
   }
} // class

}